package com.xxx.sso.config;

import com.xxx.sso.consts.RedisConst;
import com.xxx.sso.enums.ErrEnum;
import com.xxx.sso.util.HashidsUtil;
import com.xxx.sso.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author caiwl
 * @date 2020/5/2 16:23
 */
public class LoginInterceptor extends HandlerInterceptorAdapter {
    @Autowired
    private RedisService redisService;

    private String tokenHeaderName = "Authorization";
    /** Authorization=Bearer xxx... */
    private String headerPrefix = "Bearer ";
    private int headerPrefixLen = headerPrefix.length();

    private String[] excludePaths = {"/user/isLogin", "/user/login", "/async/**"};

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从请求头获取Authorization并解析出token，然后验证token
        String header;
        if (StringUtil.isEmpty(header = request.getHeader(tokenHeaderName)) || !header.startsWith(headerPrefix) || header.length() <= headerPrefixLen) {
            // 没有设置请求头，还要访问权限接口，说明前端逻辑有问题
            response403(response);
            return false;
        }
        String token = header.substring(headerPrefixLen);
        String hashId;
        if (StringUtil.isEmpty(hashId = redisService.get(token))) {
            response(response, ErrEnum.ERR_CLIENT_PERMISSION);
            return false;
        }
        Long userId;
        if ((userId = HashidsUtil.decode(hashId)) == 0) {
            response(response, ErrEnum.ERR_SERVER);
            return false;
        }
        // 刷新token过期时间
        redisService.expire(token);
        // 设置attr=token，用于退出等操作
        request.setAttribute(RedisConst.ATTR_NAME_TOKEN, token);
        // 设置attr=userId，用于获取登录用户基本信息等操作
        request.setAttribute(RedisConst.ATTR_NAME_USERID, userId);
        return super.preHandle(request, response, handler);
    }

    public String[] getExcludePaths() {
        return excludePaths;
    }

    private void response403(HttpServletResponse response) {
        response.setHeader("content-type", "text/html;charset=UTF-8");
        try {
            response.getWriter().print("<h1 style=\"text-align:center\">403 Forbidden 禁止访问</h1>");
        } catch (IOException e) {}
    }

    private void response(HttpServletResponse response, ErrEnum err) {
        response.setHeader("content-type", "application/json;charset=UTF-8");
        try {
            response.getWriter().print("{\"code\":\"" + err.getCode() + "\",\"msg\":\"" + err.getMsg() + "\"}");
        } catch (IOException e) {}
    }
}
